Skip to content

[자동차 경주] 김선아 미션 제출합니다.#42

Open
todays-sun-day wants to merge 16 commits into
woowacourse-precourse:mainfrom
woowacourse8:todays-sun-day
Open

[자동차 경주] 김선아 미션 제출합니다.#42
todays-sun-day wants to merge 16 commits into
woowacourse-precourse:mainfrom
woowacourse8:todays-sun-day

Conversation

@todays-sun-day
Copy link
Copy Markdown

[2주차] 자동차 경주 🚗

초간단 자동차 경주 게임을 구현한다.

구현한 기능 목록 📝

1. 애플리케이션을 실행하면 안내 문구를 출력하고, 자동차 이름과 시도할 횟수를 입력받는다.

경주할 자동차 이름을 입력하세요.(이름은 쉼표(,)기준으로 구분)
pobi,woni,jun
시도할 횟수는 몇 회인가요?
5

2. 쉼표(,)를 기준으로, 자동차 이름을 분리한다.

3. 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우 전진하고 4 미만일 경우 멈춘다.

4. 실행 결과 첫 출력시 '실행 결과' 문구를 출력하고, 한 횟수가 끝날 때마다 결과를 출력한다.

실행 결과
pobi : -
woni :
jun : -

5. 게임을 완료한 후 누가 우승했는지 출력하고, 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다.

최종 우승자 : pobi, jun

6. 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException 을 발생시킨 후 애플리케이션은 종료된다.

  • 자동차 이름이 5자를 초과인 경우
  • 쉼표로 구분한 각 이름이 비어있거나 공백일 경우 (예: pobi,,jun)
  • 시도할 횟수가 1 미만의 숫자인 경우 (또는 숫자가 아닌 경우)

7. 기능 목록이 정상 작동하는지 테스트 코드로 확인한다.

설계 🧩

main

racingcar
├── controller
│   └── RaceController.kt
│
├── domain
│   ├── Car.kt
│   └── Race.kt
│
├── port
│   ├── InputPort.kt
│   └── OutputPort.kt
│
├── util
│   ├── InputParser.kt
│   ├── InputValidator.kt
│   └── RandomUtils.kt
│
├── view
│   ├── InputView.kt
│   └── OutputView.kt
│
└── Application.kt (main 함수)

test

racingcar
├── controller
│   └── RaceControllerTest.kt
│
├── domain
│   ├── CarTest.kt
│   └── RaceTest.kt
│
├── util
│   ├── InputParserTest.kt
│   └── InputValidatorTest.kt
│
└── ApplicationTest.kt

과제 내용 분석 후 구현할 기능 목록을 추가함.
자동차 이름과 시도횟수 안내문구를 출력함. 리턴 값으로 입력을 받음.
MVC 패턴을 적용하여서 코드 구조를 설계함.
쉼표를 기준으로 자동차 이름을 분리함
객체지향 설계 원칙에 따라 main 함수의 역할을 프로그램 진입점으로 축소함.
원래 작성한 작업은 컨트롤러에게 위임함.
car 클래스와 race 클래스 만듦. car 클래스에 position 변수 넣어서 위치 관리함.
실행 결과 첫 출력시 '실행 결과'문구 출력함.
한 횟수가 끝날 때마다 결과를 출력함.
우승자 여러명일 경우 쉼표(,)를 이용하여 출력함.
자동차 이름이 5자를 초과한 경우, 쉼표로 구분한 각 이름이 비어있거나 공백인 경우, 시도할 횟수가 1미만의 숫자인 경우 예외로 봄.
테스트 코드 구조 추가함.
테스트 코드 기능 추가함.
기존에 ResultView에서 진행했던 우승자 찾기 부분을 Race로 이동함.
inputView에서 readTryCount 반환값을 String으로 변경함. InputValidator 에서 경우의 수를 세부적으로 나눔. 컨벤션에 맞게 양식 수정함.
test 코드 적용시 기존의 inputview, resultview 로는 console 테스트가 불가하므로 인터페이스를 추가함. 기존의 Race 는 View 의 기능도 포함하고 있었는데 순수한 객체로 수정.
기능 목록이 정상 작동하는지 테스트 코드 추가하여 확인함.
resultview 에서 outputview 로 이름 수정함.
inputport 와 outputport 인터페이스 추가함.
Copy link
Copy Markdown

@its10623 its10623 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MVC패턴을 새로 적용하신 점이 인상 깊었습니다!
2주차 과제도 수고 많으셨습니다!


object InputValidator {
fun validateCarNames(readCarNames: List<String>) {
for (carName in readCarNames) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for문보다 forEach로 람다식 활용하는것은 어떨까요!?
저도 많이 사용해보진 않았지만, forEach가 조금도 코틀린스럽고, 간결한 것 같아서 의견 드립니다!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for문보다 forEach로 람다식 활용하는것은 어떨까요!? 저도 많이 사용해보진 않았지만, forEach가 조금도 코틀린스럽고, 간결한 것 같아서 의견 드립니다!

foreach 가 더 가독성이 좋아보일 것 같기도 하네요! 감사합니다!


object InputView : InputPort {
override fun readCarNames(): String? {
println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,)기준으로 구분)")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

입력과 출력이 같이되고있어서 단일 책임 원칙에 어긋나는 것 같습니다!
print를 outputView로 분리하면 어떨까요?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이번 주 공통피드백에서도 언급은 됐지만, 상수 정의하는것도 고민해보셔야 할 것 같습니다!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

입력과 출력이 같이되고있어서 단일 책임 원칙에 어긋나는 것 같습니다! print를 outputView로 분리하면 어떨까요?

controller 를 좀 더 깔끔히 작성하고 싶어서 고민했던 부분인데, 확실히 단일 책임 원칙엔 어긋나는 것 같습니다..! 감사합니다

Copy link
Copy Markdown

@eungyeong12 eungyeong12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2주차 고생 많으셨습니다!
MVC 패턴에 따라 책임의 분리가 잘 이루어진 것 같습니다!

Comment on lines +5 to +10
interface OutputPort {
fun printFirstResult()
fun printRoundResult(car: Car)
fun printBlankLine()
fun printFinalWinner(winners: List<Car>)
} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인터페이스를 만드신 이유가 궁금해요!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인터페이스를 만드신 이유가 궁금해요!

RaceController 테스트를 위해 만들었어요! 단순 입력과 출력은 테스트의 필요성을 느끼지 못해서 따로 테스트를 만들지 않았습니다. 따라서 전체적인 경주 진행을 알아보는데 전체적인 출력보다는 필요한 부분만 출력하면 될 것으로 여겨져서 만들었습니다!

Comment on lines +6 to +8
fun getRandomInt(): Int {
return Randoms.pickNumberInRange(0, 9)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0과 9를 상수로 선언하면 좋을 것 같습니다!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0과 9를 상수로 선언하면 좋을 것 같습니다!

작은 부분이라 신경을 못 썼는데, 감사합니다!!

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

단위 테스트를 꼼꼼하게 잘 작성하셨네요!👍

Comment on lines +3 to +6
interface InputPort {
fun readCarNames(): String?
fun readTryCount(): String?
} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null을 허용하도록 하신 이유가 궁금해요!

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Console.readLine()에 빈 값을 입력해도 ""가 입력되서 굳이 nullable하게 처리하지 않아도 괜찮을 것 같습니다.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null을 허용하도록 하신 이유가 궁금해요!

Console.readLine 에서 사용자가 입력을 하지 않고, null 을 반환하면 읽어오는 순간에 바로 오류가 날까봐 널을 허용했어요! 대신 받아오는 과정에서 널일 경우 공백으로 처리해서 오류를 내보는 방식으로 작성했습니다!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Console.readLine()에 빈 값을 입력해도 ""가 입력되서 굳이 nullable하게 처리하지 않아도 괜찮을 것 같습니다.

터미널에서 Ctrl+D 나 Ctrl+Z 를 입력해서 사용자가 직접 입력의 끝을 알리면 null 로 들어온다고 하더라고요! 혹시나 해서 넣은 부분입니다!

Comment on lines +12 to +27
private fun findFinalMaxPosition(cars: List<Car>): Int {
return cars.maxOf { it.position }
}

fun findWinners(): List<Car> {
val maxPosition = findFinalMaxPosition(cars)
val winners: MutableList<Car> = mutableListOf()

for (car in cars) {
if (car.position == maxPosition) {
winners += car
}
}

return winners
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maxOffilter를 사용해서 간결하게 작성할 수 있을 것 같습니다!

fun findWinners(): List<Car> {
    val maxPosition = cars.maxOf { it.position }
    return cars.filter { it.position == maxPosition }
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maxOffilter를 사용해서 간결하게 작성할 수 있을 것 같습니다!

fun findWinners(): List<Car> {
    val maxPosition = cars.maxOf { it.position }
    return cars.filter { it.position == maxPosition }
}

filter 가 있었네요! 감사합니다 !!

Comment on lines +28 to +36
repeat(tryCount) {
race.runOneRound()

cars.forEach { car ->
outputPort.printRoundResult(car)
}

outputPort.printBlankLine()
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

controller에서 출력의 책임을 가지고 있는 것처럼 느껴져요!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

controller에서 출력의 책임을 가지고 있는 것처럼 느껴져요!

출력의 책임을 좀 더 분리하는 게 좋겠네요! 감사합니다 !

Copy link
Copy Markdown

@CommitTheKermit CommitTheKermit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코드 잘 읽었습니다. 제가 부족했던 테스트 부분이 아주 훌륭하네요. 3주차도 파이팅입니다~

Comment on lines +8 to +11
fun `Car 생성 시 position은 0이다`() {
val car = Car("pobi")
assertThat(car.position).isEqualTo(0)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제 구현에는 단위 테스트까지는 구현하지 못했는데 단위 테스트까지 완벽하시네요!

Comment on lines +3 to +6
interface InputPort {
fun readCarNames(): String?
fun readTryCount(): String?
} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Console.readLine()에 빈 값을 입력해도 ""가 입력되서 굳이 nullable하게 처리하지 않아도 괜찮을 것 같습니다.

Copy link
Copy Markdown

@jsy002514 jsy002514 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안녕하세요! 2주차 미션 수고하셨습니다. 아직 코드리뷰가 서툴러서 많이 배우고 갑니다!

package racingcar.util

object InputParser {
const val COMMA = ','
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delimeter를 따로 자료형으로 저장하는거 좋네요!
나중에 관리에도 좋아보여요. 하나 배워가요

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants